package com.ww.learn.coroutine.cancel

import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.cancelAndJoin
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import java.net.URL
import java.util.concurrent.TimeUnit

val url = "https://www.baidu.com"

fun getResponse() = URL(url).readText()

suspend fun fetchResponse(callAsync: Boolean) = coroutineScope {
    try {
        val response = if (callAsync) {
            async { getResponse() }.await()
        } else {
            getResponse()
        }
        println(response)
    } catch (ex: CancellationException) {
        println("fetchResponse called with callAsync $callAsync: ${ex.message}")
    }
}

suspend fun compute(checkActive: Boolean) = coroutineScope {
    var count = 0L
    val max = 10000000000

    while (if (checkActive) {
            isActive
        } else (count < max)
    ) {
        count++
    }
    if (count == max) {
        println("compute, checkActive $checkActive ignored cancellation")
    } else {
        println("compute, checkActive $checkActive bailed out early")
    }
}

fun main() = runBlocking {
    val job = launch(Dispatchers.Default) {
        launch { compute(false) }
        launch { compute(true) }
        launch { fetchResponse(false) }
        launch { fetchResponse(true) }
    }
    println("Let them run...")
    TimeUnit.SECONDS.sleep(1)
    println("OK, that's enough, cancel")
    job.cancelAndJoin()
}